//////////////////////////////////////////////////////////////////////////////////////////////
//	File			:	"GameplayState.cpp"
//
//	Author			:	Mike Davis, Matt Stover, James Thornton, Keith Webster
//	
//	Project			:	TacWars
//
//	Last Modified	:	11/6/2013
//
//	Purpose			:	
//
//////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "GameplayState.h"
#include "SelectSquadState.h"
#include "../GameObjects/PrecisionGauge.h"
#include "WorldMapState.h"
#include "PauseState.h"
#include "../../SGD Wrappers/CSGD_Direct3D.h"
#include "../../SGD Wrappers/CSGD_DirectInput.h"
#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include "../../SGD Wrappers/CSGD_XAudio2.h"
#include "../../SGD Wrappers/CSGD_MessageSystem.h"
#include "../../SGD Wrappers/CSGD_EventSystem.h"
#include "../../SGD Wrappers/SGD_String.h"
#include "../../SGD Wrappers/SGD_Math.h"
#include "../MapSystem/BattleMap.h"
#include "../MapSystem/MapManager.h"
#include "../ParticleSystem/Emitter.h"
#include "../Game.h"
#include "../GameObjects/General.h"
#include "../GameObjects/Knight.h"
#include "../GameObjects/Ranger.h"
#include "../GameObjects/Priest.h"
#include "../GameObjects/Berserker.h"
#include <cassert>
#include "../GameObjects/Player.h"
#include "../GameObjects/Cursor.h"
#include "../Interface.h"
#include "../MessageSystem/Message.h"
#include "../MessageSystem/UnitDeadMessage.h"
#include "../MessageSystem/UnitTurnEndMessage.h"
#include "BattleReportState.h"
#include "../TinyXML/tinyxml.h"
#include "GameLoadState.h"
#include "OptionsState.h"

GameplayState* GameplayState::GetInstance()
{
	static GameplayState Instance;

	return &Instance;
}
GameplayState::GameplayState()
{
	EM->GetInstance()->LoadEmitter("Cursor");
	cursor = new Cursor;

	testHPdmg = testLPdmg = 0;
	MS = nullptr;
	ES = nullptr;



}
GameplayState::~GameplayState()
{
}
/*virtual*/ void GameplayState::Enter()
{
	turnCount = 0;
	titleImgID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/BMap.png"));
	//mapImgID = WorldMapState::GetInstance()->GetSelectedMap();
	cursorImgID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/Cursor.png"));
	heartID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/Heart.png"));
	swordID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/sword.png"));
	crownID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/CrownStat.jpg"));
	portraitID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/face.png"));
	bootID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/boot.jpg"));
	bowID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("resource/Images/face.png"));

	player2 = GameLoadState::GetInstance()->CreatePlayer();

	General* g = new General();
	g->SetPosX(256+32);
	g->SetPosY(256+32);
	g->SetImgID(Game::GetInstance()->GetGeneralImgID());
	g->SetOwner(player2);
	player2->AddUnit(g, player2->Squad);

	moverange = attackrange = false;
	MS = CSGD_MessageSystem::GetInstance();
	MS->Initialize(&MessageProc);
	MM = MapManager::GetInstance();

	ES = CSGD_EventSystem::GetInstance();
	MM->Load("resource/Maps/TestMap.xml");
	player1 = SelectSquadState::GetInstance()->playerOne;
	cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,0)].element->position.x + 32);
	cursor->SetPosY(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,0)].element->position.y + 32);
	cursor->SetWidth(64);
	cursor->SetHeight(64);
	worldX = MM->GetMap()->GetWidth() * 64;
	worldY = MM->GetMap()->GetHeight() * 64;
	for(unsigned int i = 0; i < player1->Squad.size(); i++)
	{
		MM->GetMap()->GetMap()[MM->GetMap()->FindTile(player1->Squad[i]->GetPosX() / 64,
			player1->Squad[i]->GetPosY() / 64)].element->OccupyingUnit = player1->Squad[i];
		player1->Squad[i]->SetOccupyingTile(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(player1->Squad[i]->GetPosX() / 64,
			player1->Squad[i]->GetPosY() / 64)].element);
	}
	for(unsigned int i = 0; i < player2->Squad.size(); i++)
	{
		MM->GetMap()->GetMap()[MM->GetMap()->FindTile(player2->Squad[0]->GetPosX() / 64, 
			player2->Squad[0]->GetPosY() / 64)].element->OccupyingUnit = player2->Squad[0];
		player2->Squad[i]->SetOccupyingTile(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(player2->Squad[i]->GetPosX() / 64,
			player2->Squad[i]->GetPosY() / 64)].element);
	}
	animManager = CAnimationManager::GetInstance();
	aniInfo = new AnimInfo;
	IFace = new Interface();
}
/*virtual*/ void GameplayState::Exit()
{
		
}
/*virtual*/ bool GameplayState::Input()
{
	CSGD_DirectInput* DI = CSGD_DirectInput::GetInstance();

	if(DI->KeyPressed(DIK_ESCAPE) == true)
	{
		Game::GetInstance()->PushState(PauseState::GetInstance());
	}
	
		if(DI->KeyPressedEx(DIK_T) == true)
		{
			aniInfo = animManager->GetAnimationInfo(0);
			player1->Squad[0]->StartStopAnimation();
			animManager->PlayAnimation( aniInfo->currAnimation, *player1->Squad[0]->GetAnimInfo(), player1->Squad[0] );
			return true;
		}
		/*
		if(DI->KeyPressedEx(DIK_Y) == true)
		{
			aniInfo = animManager->GetAnimationInfo(2);
			player1->Squad[3]->StartStopAnimation();
			animManager->PlayAnimation( aniInfo->currAnimation, *player1->Squad[3]->GetAnimInfo(), player1->Squad[3] );
			return true;
		}
		if(DI->KeyPressedEx(DIK_U) == true)
		{
			aniInfo = animManager->GetAnimationInfo(1);
			player1->Squad[1]->StartStopAnimation();
			animManager->PlayAnimation( aniInfo->currAnimation, *player1->Squad[1]->GetAnimInfo(), player1->Squad[1] );
			return true;
		}
		if(DI->KeyPressedEx(DIK_H) == true)
		{
			aniInfo = animManager->GetAnimationInfo(1);
			animManager->PlayAnimation( aniInfo->currAnimation, *player1->Squad[0]->GetAnimInfo(), player1->Squad[0] );
			return true;
		}
		if(DI->KeyPressedEx(DIK_J) == true)
		{
			aniInfo = animManager->GetAnimationInfo(3);
			animManager->PlayAnimation( aniInfo->currAnimation, *player1->Squad[2]->GetAnimInfo(), player1->Squad[2] );
			return true;
		}*/
		if(DI->KeyPressedEx(DIK_S) == true)
		{
			for(unsigned int i = 0; i < player1->Squad.size()-1; i++)
			{
				if(player1->Squad[i]->GetAnimInfo()->filePath != "")
				{
					aniInfo = player1->Squad[i]->GetAnimInfo();
					aniInfo->IsPlaying = false;
					animManager->StopAnimation(player1->Squad[i]->GetAnimInfo()->currAnimation, *aniInfo, player1->Squad[i]);
				}
			}
		}

		if(DI->KeyPressed(DIK_RETURN) == true)
		{
			//check tile's occupying unit. if so, select them
			if(selected == nullptr)
			{
				if(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit != NULL)
				{
					//int test = MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64);
					if(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit->GetOwner() == player1)
					{
						selected = MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit;
						if(selected->GethasMoved() != true)
						{
							selected->SetState(1);
							//moverange = true;
						}
					}
				}
			}
			else if(selected->GetStateID() == 1)
			{
				selected->Entity::Move(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element);
				selected->SetState(2);
				selected = nullptr;
			}
			else if(selected->GetStateID() == 2)
			{
				if(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit != nullptr)
					Game::GetInstance()->PushState(PrecisionGauge::GetInstance());
			}

		}

		if(DI->KeyPressed(DIK_LEFT) == true)
		{
			if(cursor->GetPosX()/64-1 < 0)
				cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,0)].element->position.x + 32);
			else
				cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64-1,0)].element->position.x * 64 + 32);
		}
		else if(DI->KeyPressed(DIK_RIGHT) == true)
		{
			//int test2 = cursor->GetPosX();
			//int test = MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64+1,0)].element->position.x * 64;
			if(cursor->GetPosX()/64+1 > MM->GetMap()->GetWidth())
				cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(MM->GetMap()->GetWidth(),0)].element->position.x + 32);
			else
				cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64+1,0)].element->position.x * 64 + 32);
		}
		else if(DI->KeyPressed(DIK_UP) == true)
		{
			if(cursor->GetPosY()/64-1 < 0)
				cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,0)].element->position.y + 32);
			else
				cursor->SetPosY(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,cursor->GetPosY()/64-1)].element->position.y * 64 + 32);
		}
		else if(DI->KeyPressed(DIK_DOWN) == true)
		{
			/*			if(cursor->GetPosY()/64+1 > 0)
			cursor->SetPosX(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,0)].element->position.y + 32);
			*///else
			cursor->SetPosY(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(0,cursor->GetPosY()/64+1)].element->position.y * 64 + 32);
		}

		if(DI->KeyPressed(DIK_K) == true)
		{
			if(player1->Squad.size() != 0)
				player1->Squad[0]->SetHealth(0);
		}
		if(DI->KeyDown(DIK_M) == true)
		{
			if(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit != NULL)
			{
				moverange = true;
			}
		}
		if(DI->KeyDown(DIK_N) == true)
		{
			if(MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit != NULL)
			{
				attackrange = true;
			}
		}

	

	//StayInWorld();
	return true;
}
/*virtual*/ void GameplayState::Update( float fElapsedTime )
{
	
		target = MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit;
		for( int i = 0; i < (int)player1->Squad.size(); i++)
		{
			if(player1->Squad[i]->GetAnimInfo()->IsPlaying == true)
			{
				aniInfo = player1->Squad[i]->GetAnimInfo();
				animManager->UpdateAnimation(aniInfo->currAnimation, *aniInfo, fElapsedTime);
			}
		}

		if(turnCount % 2 == 0)
		{
			if(player1->Squad.size() == 0 || player2->Squad.size() == 0)
			{
				Game::GetInstance()->PushState(BattleReportState::GetInstance());
				SaveGameInfo();
			}
			if(player1->AvailableUnits.size() == 0)
			{
				for(unsigned int i = 0; i < player1->Squad.size(); i++)
				{
					player1->AddUnit(player1->Squad[i], player1->AvailableUnits);
				}
			}
			//update tiles
			player1->UpdateAll(fElapsedTime, player1->AvailableUnits);
			//update UI
			if(player1->AvailableUnits.size() == 0)
			{
				turnCount++;
			}
		}
		else
		{
			//run AI turn
			turnCount++;
		}

		SetCamX(cursor->GetPosX() - Game::GetInstance()->GetScreenWidth() /2);
		SetCamY(cursor->GetPosY() - Game::GetInstance()->GetScreenHeight() /2);
		//this slows it down
		IFace->Update(fElapsedTime);
	
	

	MS->ProcessMessages();
	ES->ProcessEvents();
}
/*virtual*/ void GameplayState::Render()
{

	//this will go away and will replace with map
	CSGD_TextureManager::GetInstance()->Draw(titleImgID, 0, 0);
	MapManager::GetInstance()->GetMap()->Render(GetCamX(),GetCamY());
	//CSGD_TextureManager::GetInstance()->Draw(mapImgID, 0 - GetCamX(), 0 - GetCamY(), 1.0f, 1.0f);
	CSGD_TextureManager::GetInstance()->Draw(cursorImgID, cursor->GetPosX() - GetCamX(), cursor->GetPosY() - GetCamY(), 1.0f, 1.0f);


	//render tiles before player
	//player1->RenderAll(player1->Squad);
	//render UI
	IFace->Render();
	if(moverange)
	{
		MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit->ShowMoveRange();
		moverange = false;
	}
	if(attackrange)
	{
		MM->GetMap()->GetMap()[MM->GetMap()->FindTile(cursor->GetPosX()/64,cursor->GetPosY()/64)].element->OccupyingUnit->ShowAttackRange();
		attackrange = false;
	}

}

Cursor* GameplayState::GetCursor()
{
	return cursor;
}
void GameplayState::StayInWorld()
{
	if(cursor->GetPosX() < 0)
		cursor->SetPosX(0);
	if(cursor->GetPosX() > GetWorldX() - cursor->GetWidth())
		cursor->SetPosX(GetWorldX() - cursor->GetWidth());
	if(cursor->GetPosY() < 0)
		cursor->SetPosY(0);
	if(cursor->GetPosY() > GetWorldY() - cursor->GetHeight())
		cursor->SetPosY(GetWorldY() - cursor->GetHeight());
}
void GameplayState::MessageProc(IMessage* pMsg)
{
	switch(pMsg->GetMessageID())
	{
	case MSG_UNIT_DEAD:
		{
			UnitDeadMessage* killMsg = dynamic_cast<UnitDeadMessage*>(pMsg);
			assert(killMsg != nullptr && "Game::MessageProc - MSGD_UNIT_DEAD is not a destroyentitymsg");

			Entity* entity = killMsg->GetEntity();

			GameplayState::GetInstance()->player1->RemoveUnit(entity, GameplayState::GetInstance()->player1->Squad);
		}
		break;
	case MSG_UNIT_FINISHED:
		{
			UnitTurnEndMessage* finishMsg = dynamic_cast<UnitTurnEndMessage*>(pMsg);
			assert(finishMsg != nullptr && "Game::MessageProc - MSG_UNIT_FINISHED is not a removeEntityMsg");

			Entity* entity = finishMsg->GetEntity();

			GameplayState::GetInstance()->player1->RemoveUnit(entity, GameplayState::GetInstance()->player1->AvailableUnits);
		}
	}
}
void GameplayState::SaveGameInfo()
{

	TiXmlDocument info;

	TiXmlElement* ele = new TiXmlElement("Saves");

	//ele->SetAttribute("Name", 
	ele->SetAttribute("Level", WorldMapState::GetInstance()->GetLevelSlot());

	for(unsigned int i = 0; i < player1->Army.size(); i++)
	{
		TiXmlElement* units = new TiXmlElement("Units");
		units->SetAttribute("UnitType", player1->Army[i]->GetType());
		ele->LinkEndChild(units);
	}

	TiXmlElement* setting = new TiXmlElement("Settings");
	setting->SetAttribute("MusicVolume", OptionsState::GetInstance()->GetMusVol());
	setting->SetAttribute("SFXVolume", OptionsState::GetInstance()->GetSfxVol());
	ele->LinkEndChild(setting);
	info.LinkEndChild(ele);

	ostringstream T;
	T << "resource/Save Profiles/Slot " << GameLoadState::GetInstance()->GetSaveSlot() << ".xml";
	info.SaveFile(T.str().c_str());
}
